package main

import (
	"errors"
	"fmt"
	"runtime"
)

/**
内建函数recover允许程序管理恐慌过程中的Go程序。
在defer的函数中，执行recover调用会取回传至panic调用的错误值，恢复正常执行，停止恐慌过程。
若recover在defer的函数之外被调用，它将不会停止恐慌过程序列。
在此情况下，或当该Go程不在恐慌过程中时，或提供给panic的实参为nil时，
recover就会返回nil。
*/

// capturePanicStack 捕获 panic 并输出栈信息
func capturePanicStack() {
	if r := recover(); r != nil {
		fmt.Println("捕获到 panic:", r)

		// 获取当前 goroutine 的栈信息
		buf := make([]byte, 4096)
		n := runtime.Stack(buf, false)
		fmt.Printf("堆栈信息:\n%s\n", buf[:n])
	}
}

func test() {
	// 使用 capturePanicStack 来捕获错误及栈信息
	defer capturePanicStack()

	num := 10
	num2 := 0
	result := num / num2
	fmt.Println(result)
}

// 自定义错误
func test01() (err error) {
	num := 10
	num2 := 0
	if num2 == 0 {
		return errors.New("除数不能为0")
	}
	result := num / num2
	fmt.Println(result)
	return nil
}

// panic 内建函数处理：
func main() {
	test()
	err := test01()
	if err != nil {
		fmt.Println("自定义错误：", err)
		panic(err) // 加上该函数，后面的代码不会执行
	}
	fmt.Println("test函数执行完成")
}
